package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.UacGroupRoleActionMapper;
import com.csun.cmny.provider.model.constant.RoleConstant;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.action.ActionMainQueryDto;
import com.csun.cmny.provider.model.dto.group.GroupActionQueryDto;
import com.csun.cmny.provider.model.dto.group.GroupRoleActionListDto;
import com.csun.cmny.provider.model.dto.group.GroupRoleAssignActionDto;
import com.csun.cmny.provider.model.dto.group.GroupRoleDto;
import com.csun.cmny.provider.model.dto.menu.MenuQueryDto;
import com.csun.cmny.provider.model.dto.role.AssignActionDto;
import com.csun.cmny.provider.model.dto.role.AssignMenuDto;
import com.csun.cmny.provider.model.exceptions.UacBizException;
import com.csun.cmny.provider.model.vo.BindAuthVo;
import com.csun.cmny.provider.model.vo.MenuVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.TreeUtil;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-07-21 13:09
 * @Description: the class uac group role action service
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UacGroupRoleActionServiceImpl extends BaseService<UacGroupRoleAction>
        implements UacGroupRoleActionService {

    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private UacGroupRoleActionMapper uacGroupRoleActionMapper;
    @Resource
    private UacGroupService uacGroupService;
    @Resource
    private UacRoleService uacRoleService;
    @Resource
    private UacMenuService uacMenuService;
    @Resource
    private UacActionService uacActionService;
    @Resource
    private UacRoleMenuService uacRoleMenuService;
    @Resource
    private UacRoleActionService uacRoleActionService;
    @Resource
    private UacGroupRoleMenuService uacGroupRoleMenuService;

    /**
     * 批量移除机构角色功能
     *
     * @param groupRoleActionListDto the group role action list dto
     *
     * @return the int.
     */
    @Override
    public Integer batchDeleteRoleAction(GroupRoleActionListDto groupRoleActionListDto) {

        Long groupId = groupRoleActionListDto.getGroupId();
        Long roleId = groupRoleActionListDto.getRoleId();
        List<Long> actionIdList = groupRoleActionListDto.getActionIdList();

        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

//        Preconditions.checkArgument(PublicUtil.isNotEmpty(actionIdList),
//                cmnyMessageSource.getMessage("action.id.list.null", null));

        return uacGroupRoleActionMapper.batchDeleteRoleAction(groupId, roleId, actionIdList);
    }

    /**
     * 分配机构角色功能
     *
     * @param groupRoleAssignActionDto the group role assign action dto
     * @return the int.
     */
    @Override
    public Integer assignRoleAction(GroupRoleAssignActionDto groupRoleAssignActionDto) {

        Long groupId = groupRoleAssignActionDto.getGroupId();
        Long roleId = groupRoleAssignActionDto.getRoleId();
        List<AssignActionDto> assignActionDtoList = groupRoleAssignActionDto.getAssignActionDtoList();

        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        Preconditions.checkArgument(PublicUtil.isNotEmpty(assignActionDtoList),
                cmnyMessageSource.getMessage("action.list.null", null));

        // TODO 校验角色Id是否存在

        // TODO 校验菜单Id是否存在

        List<Long> checkActionList = Lists.newArrayList();
        List<Long> deleteActionList = Lists.newArrayList();
        // 将分配的菜单按照'选中','移除'分为两组
        for (AssignActionDto aad : assignActionDtoList) {
            switch (aad.getCheck()) {
                case RoleConstant.CHECK_STATUS_SLT :
                    checkActionList.add(aad.getActionId());
                    break;
                case RoleConstant.CHECK_STATUS_RID :
                    deleteActionList.add(aad.getActionId());
                    break;
            }
        }

        int result = 0;
        // 批量添加角色菜单
        if (PublicUtil.isNotEmpty(checkActionList)) {
            result += uacGroupRoleActionMapper.batchSaveRoleAction(groupId, roleId, checkActionList);
        }

        // 批量删除角色菜单
        if (PublicUtil.isNotEmpty(deleteActionList)) {
            result += uacGroupRoleActionMapper.batchDeleteRoleAction(groupId, roleId, deleteActionList);
        }

        return result;
    }

    /**
     * 获取机构角色功能列表
     *
     * @param groupActionQueryDto the group action query dto
     * @return the page info.
     */
    @Override
    public PageInfo queryRoleActionListWithPage(GroupActionQueryDto groupActionQueryDto) {

        List<UacAction> uacActionList = Lists.newArrayList();
        Long groupId = groupActionQueryDto.getGroupId();
        Long roleId = groupActionQueryDto.getRoleId();

        // 校验角色Id是否为空
        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        // 校验机构Id是否为空
        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        GroupRoleDto groupRoleDto = new GroupRoleDto();
        groupRoleDto.setGroupId(groupId);
        groupRoleDto.setRoleId(roleId);
        // List<Long> roleMenuIdList = uacGroupRoleMenuService.getCheckedMenuList(groupRoleDto);
        List<Long> roleMenuIdList = uacActionService.getCheckedMenuList(roleId);
        if (PublicUtil.isEmpty(roleMenuIdList)) {
            return new PageInfo<>(uacActionList);
        }

        // 查询指定菜单下所有的子菜单
        if (PublicUtil.isNotEmpty(groupActionQueryDto.getMenuId())) {
            List<Long> menuIdList = uacMenuService.queryMenuAndSubMenuIdsInMenuList(groupActionQueryDto.getMenuId(), roleMenuIdList);
            groupActionQueryDto.setMenuId(null);
            groupActionQueryDto.setMenuIdList(menuIdList);
        }

        // 获取所有绑定的按钮权限Id集合
        List<Long> checkedAuthList = getCheckedActionList(groupRoleDto);

        // 分页
        PageHelper.startPage(groupActionQueryDto.getPageNum(), groupActionQueryDto.getPageSize());
        if (PublicUtil.isEmpty(checkedAuthList)) {
            uacActionList = uacGroupRoleActionMapper.queryActionList(groupActionQueryDto);
        } else {
            groupActionQueryDto.setActionIds(StringUtils.join(checkedAuthList, ","));
            // 查询
            uacActionList= uacGroupRoleActionMapper.queryRoleActionList(groupActionQueryDto);
        }

        return new PageInfo<>(uacActionList);
    }

    /**
     * 批量添加机构角色功能
     *
     * @param groupId           the group id
     * @param uacRoleActionList the uac role action list
     *
     * @return the int.
     */
    @Override
    public Integer batchSaveGroupRoleAction(Long groupId, List<UacRoleAction> uacRoleActionList) {

        return uacGroupRoleActionMapper.batchSaveGroupRoleAction(groupId, uacRoleActionList);
    }

    /**
     * get group role action tree
     *
     * @param groupRoleDto the group role dto
     *
     * @return the bind auth vo
     */
    @Override
    public BindAuthVo getGroupRoleActionTree(GroupRoleDto groupRoleDto) {

        BindAuthVo bindAuthVo = new BindAuthVo();
        Long groupId = groupRoleDto.getGroupId();
        Long roleId = groupRoleDto.getRoleId();

        // 校验角色Id是否为空
        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        // 校验机构Id是否为空
        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        // 校验机构是否存在
        UacGroup uacGroup = uacGroupService.selectByKey(groupId);
        if (PublicUtil.isEmpty(uacGroup)) {
            throw new UacBizException(ErrorCodeEnum.UAC10015016);
        }

        // 校验角色是否存在
        UacRole uacRole = uacRoleService.selectByKey(roleId);
        if (PublicUtil.isEmpty(uacRole)) {
            throw new UacBizException(ErrorCodeEnum.UAC10012009);
        }

        List<UacMenu> uacMenus;
        List<UacAction> uacActions;

        // 获取所有绑定的菜单和按钮权限Id集合
        List<Long> checkedAuthList = uacGroupRoleMenuService.getCheckedMenuList(groupRoleDto);
        if (PublicUtil.isEmpty(checkedAuthList)) {
            // 如果没有选中任何菜单, 为角色全部的菜单
            checkedAuthList = uacActionService.getCheckedMenuList(roleId);
        }

        if (PublicUtil.isEmpty(checkedAuthList)) {
            return bindAuthVo;
        }

        if (PublicUtil.isEmpty(checkedAuthList)) {
            uacMenus = uacRoleMenuService.queryRoleMenuList(groupRoleDto);
        } else {
            groupRoleDto.setMenuIds(StringUtils.join(checkedAuthList, ","));
            // 查询
            uacMenus = uacRoleMenuService.queryRoleMenuListWithCheck(groupRoleDto);
        }

        checkedAuthList = getCheckedActionList(groupRoleDto);
        if (PublicUtil.isEmpty(checkedAuthList)) {
            uacActions = uacRoleActionService.queryRoleActionList(groupRoleDto);
        } else {
            groupRoleDto.setActionIds(StringUtils.join(checkedAuthList, ","));
            uacActions = uacRoleActionService.queryRoleActionListWithCheck(groupRoleDto);
        }


        // 合并菜单和按钮权限 递归生成树结构
        List<MenuVo> menuVoList = uacMenuService.getAuthList(uacMenus, uacActions);

        List<MenuVo> tree = TreeUtil.getChildMenuVos(menuVoList, 0L);

        bindAuthVo.setAuthTree(tree);
        bindAuthVo.setCheckedAuthList(checkedAuthList);

        return bindAuthVo;
    }

    /**
     * 获取选中的功能列表
     *
     * @param groupRoleDto the group role dto
     *
     * @return the list
     */
    @Override
    public List<Long> getCheckedActionList(GroupRoleDto groupRoleDto) {

        Long groupId = groupRoleDto.getGroupId();
        Long roleId = groupRoleDto.getRoleId();

        // 校验角色Id是否为空
        Preconditions.checkArgument(roleId != null,
                cmnyMessageSource.getMessage("role.id.null", null));

        // 校验机构Id是否为空
        Preconditions.checkArgument(groupId != null,
                cmnyMessageSource.getMessage("group.id.null", null));

        return uacGroupRoleActionMapper.getCheckedActionList(groupRoleDto);
    }

    /**
     * select count by role id and action id list
     *
     * @param roleId       the role id
     * @param actionIdList the action id list
     *
     * @return the int
     */
    @Override
    public int selectCountRoleIdAndActionIdList(Long roleId, List<Long> actionIdList) {

        return uacGroupRoleActionMapper.selectCountRoleIdAndActionIdList(roleId, actionIdList);
    }

    /**
     * query role action
     *
     * @param uacGroupRoleAction the uac group role action
     * @return the uac action
     */
    @Override
    public UacAction queryRoleAction(UacGroupRoleAction uacGroupRoleAction) {

        UacAction uacAction = uacActionService.selectByKey(uacGroupRoleAction.getActionId());
        if (PublicUtil.isEmpty(uacAction)) {
            return null;
        } else {
            UacGroupRoleAction uacGroupRoleActionQuery = uacGroupRoleActionMapper.selectOne(uacGroupRoleAction);
            if (PublicUtil.isNotEmpty(uacGroupRoleActionQuery)) {
                uacAction.setCheck(1);
            }
        }

        return uacAction;
    }

    /**
     * select count action id and role id list
     *
     * @param actionId       action id
     * @param deleteRoleList delete role list
     *
     * @return the int.
     */
    @Override
    public int selectCountActionIdAndRoleIdList(Long actionId, List<Long> deleteRoleList) {

        return uacGroupRoleActionMapper.selectCountActionIdAndRoleIdList(actionId, deleteRoleList);
    }

}
